using DeviceCommons.DeviceMessages.Enums;

namespace DeviceCommons.DeviceMessages.Factories
{
    /// <summary>
    /// 设备状态配置实现
    /// </summary>
    public class DeviceStateConfiguration : IDeviceStateConfiguration
    {
        private readonly Dictionary<byte, StateDefinition> _stateDefinitionMap;

        public DeviceStateConfiguration(byte deviceType, IEnumerable<StateDefinition> stateDefinitions)
        {
            DeviceType = deviceType;
            StateDefinitions = stateDefinitions.ToList().AsReadOnly();
            
            // 创建状态ID到定义的映射，提高查找效率
            _stateDefinitionMap = StateDefinitions.ToDictionary(sd => sd.Sid);
        }

        public byte DeviceType { get; }

        public IReadOnlyList<StateDefinition> StateDefinitions { get; }

        public StateDefinition? GetStateDefinition(byte sid)
        {
            return _stateDefinitionMap.TryGetValue(sid, out var definition) ? definition : null;
        }

        public bool ValidateStateValue(byte sid, object value)
        {
            var definition = GetStateDefinition(sid);
            if (definition == null)
                return false;

            // 基本类型验证
            if (!IsValueTypeCompatible(value, definition.ValueType))
                return false;

            // 自定义验证规则
            if (definition.ValidationRule != null && !definition.ValidationRule(value))
                return false;

            return true;
        }

        /// <summary>
        /// 检查值类型是否兼容
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="expectedType">期望的类型</param>
        /// <returns>是否兼容</returns>
        private bool IsValueTypeCompatible(object value, StateValueTypeEnum expectedType)
        {
            if (value == null)
                return false;

            return expectedType switch
            {
                StateValueTypeEnum.String => value is string,
                StateValueTypeEnum.Int32 => value is int,
                StateValueTypeEnum.Int16 => value is short,
                StateValueTypeEnum.UInt16 => value is ushort,
                StateValueTypeEnum.Float32 => value is float,
                StateValueTypeEnum.Double => value is double,
                StateValueTypeEnum.Bool => value is bool,
                StateValueTypeEnum.Binary => value is byte[],
                StateValueTypeEnum.Timestamp => value is ulong,
                _ => false
            };
        }

        /// <summary>
        /// 获取必需的状态定义
        /// </summary>
        /// <returns>必需的状态定义列表</returns>
        public IEnumerable<StateDefinition> GetRequiredStates()
        {
            return StateDefinitions.Where(sd => sd.IsRequired);
        }

        /// <summary>
        /// 检查是否包含所有必需的状态
        /// </summary>
        /// <param name="providedSids">提供的状态ID集合</param>
        /// <returns>是否包含所有必需状态</returns>
        public bool ContainsAllRequiredStates(IEnumerable<byte> providedSids)
        {
            var requiredSids = GetRequiredStates().Select(sd => sd.Sid).ToHashSet();
            var providedSidsSet = providedSids.ToHashSet();
            return requiredSids.IsSubsetOf(providedSidsSet);
        }

        /// <summary>
        /// 获取缺失的必需状态
        /// </summary>
        /// <param name="providedSids">提供的状态ID集合</param>
        /// <returns>缺失的必需状态ID列表</returns>
        public IEnumerable<byte> GetMissingRequiredStates(IEnumerable<byte> providedSids)
        {
            var requiredSids = GetRequiredStates().Select(sd => sd.Sid).ToHashSet();
            var providedSidsSet = providedSids.ToHashSet();
            return requiredSids.Except(providedSidsSet);
        }

        /// <summary>
        /// 验证状态完整性
        /// </summary>
        /// <param name="providedSids">提供的状态ID集合</param>
        /// <returns>验证结果</returns>
        public (bool IsValid, IEnumerable<byte> MissingStates) ValidateStateCompleteness(IEnumerable<byte> providedSids)
        {
            var missingStates = GetMissingRequiredStates(providedSids);
            var isValid = !missingStates.Any();
            return (isValid, missingStates);
        }
    }
}
